/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * invulgotracker
 * Copyright (C) Thomas Andersen 2011 <thomas.1.andersen@gmail.com>
 * 
 * invulgotracker is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * invulgotracker is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <glade/glade.h>

#include "config.h"
#include "util.h"

#include "prefs.h"

#include "task-view.h"
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xmlwriter.h>
#include <libxml/encoding.h>

#include "invulgotrackerapp.h"
#include "gettextmacro.h"


#define MY_ENCODING "ISO-8859-1"


const gchar *Prefs::colorText[] = {
    _("none"),
    _("red"),
    _("grey"),
    _("yellow"),
    _("blue"),
    _("cyan"),
    _("magenta"),
    _("black"),
    _("white"),
    _("darkred"),
    _("darkgrey"),
    _("darkblue"),
    NULL,
};

const gchar *Prefs::colorValue[] = {
    "",
    "red",
    "grey",
    "yellow",
    "blue",
    "cyan",
    "magenta",
    "black",
    "white",
    "darkred",
    "darkgrey",
    "darkblue",
    NULL,
};

extern "C" gboolean on_dialogPrefs_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_CANCEL);
    return TRUE;
}


Prefs::Prefs()
{
    hideOnMinimize = TRUE;
    hideOnClose = TRUE;
    warnOnDate = TRUE;
    warnOnTaskDelete = TRUE;
    warnOnTimeDelete = TRUE;
    insertEndTask = FALSE;
    saveWindowSizes = TRUE;
    endTaskId = 0;
    sickTaskId = 0;
    holidayTaskId = 0;
    savedWindowWidth = 0;
    savedWindowHeight = 0;
    savedWindowMaximized = FALSE;
    savedVPanePosition = 0;
    savedHPanePosition = 0;
    showSummaryPercentage = FALSE;
    hideTaskDone = TRUE;
    doneColor = 2;
    deadlineColor = 1;
    workhourMonFrom = TaskTime("09:00");
    workhourMonTo = TaskTime("17:00");
    workhourTueFrom = TaskTime("09:00");
    workhourTueTo = TaskTime("17:00");
    workhourWedFrom = TaskTime("09:00");
    workhourWedTo = TaskTime("17:00");
    workhourThuFrom = TaskTime("09:00");
    workhourThuTo = TaskTime("17:00");
    workhourFriFrom = TaskTime("09:00");
    workhourFriTo = TaskTime("17:00");
    workhourSatFrom = TaskTime("00:00");
    workhourSatTo = TaskTime("00:00");
    workhourSunFrom = TaskTime("00:00");
    workhourSunTo = TaskTime("00:00");

    Load();
    endWidget = NULL;
    sickWidget = NULL;
    holidayWidget = NULL;
    window = NULL;
    subscriber = NULL;
}

Prefs::~Prefs()
{
    if (endWidget)
        gtk_widget_destroy(endWidget);
    if (sickWidget)
        gtk_widget_destroy(sickWidget);
    if (holidayWidget)
        gtk_widget_destroy(holidayWidget);
    if (window) {
        g_signal_handler_disconnect(window, responseHandler);
        gtk_widget_hide(window);
    }
}

const gchar *Prefs::GetColorDone()
{
    if (doneColor >= (long)(sizeof(colorValue)/sizeof(colorValue[0])))
        return NULL;
    return colorValue[doneColor];
}

const gchar *Prefs::GetColorDeadline()
{
    if (deadlineColor >= (long)(sizeof(colorValue)/sizeof(colorValue[0])))
        return NULL;
    return colorValue[deadlineColor];
}

int Prefs::GetWorkhours(int weekDay)
{
    int minutes = 0;

    switch(weekDay)
    {
    case 0: minutes = workhourSunTo.SubTime(workhourSunFrom).Minutes(); break;
    case 1: minutes = workhourMonTo.SubTime(workhourMonFrom).Minutes(); break;
    case 2: minutes = workhourTueTo.SubTime(workhourTueFrom).Minutes(); break;
    case 3: minutes = workhourWedTo.SubTime(workhourWedFrom).Minutes(); break;
    case 4: minutes = workhourThuTo.SubTime(workhourThuFrom).Minutes(); break;
    case 5: minutes = workhourFriTo.SubTime(workhourFriFrom).Minutes(); break;
    case 6: minutes = workhourSatTo.SubTime(workhourSatFrom).Minutes(); break;
    }
    return minutes;
}

TaskTime Prefs::GetWorkdayStart(int weekDay)
{
    switch(weekDay)
    {
    case 0: return workhourSunFrom;
    case 1: return workhourMonFrom;
    case 2: return workhourTueFrom;
    case 3: return workhourWedFrom;
    case 4: return workhourThuFrom;
    case 5: return workhourFriFrom;
    case 6: return workhourSatFrom;
    }
    return TaskTime();
}

TaskTime Prefs::GetWorkdayEnd(int weekDay)
{
    switch(weekDay)
    {
    case 0: return workhourSunTo;
    case 1: return workhourMonTo;
    case 2: return workhourTueTo;
    case 3: return workhourWedTo;
    case 4: return workhourThuTo;
    case 5: return workhourFriTo;
    case 6: return workhourSatTo;
    }
    return TaskTime();
}

extern "C" void on_prefs_response(GtkDialog *dialog, gint response_id, gpointer user_data)
{
    ((Prefs *)user_data)->Response(response_id);
}

void Prefs::Show(INotify *subscriber)
{
    this->subscriber = subscriber;

    /* Get window. */
    window = glade_xml_get_widget (InvulgoTrackerApp::gxml, "dialogPrefs");

    /* Setup */
    GtkWidget *widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonHide");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), hideOnMinimize);
    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonHideClose");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), hideOnClose);
    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonWarn");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), warnOnDate);
    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonWarnTaskDelete");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), warnOnTaskDelete);
    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonWarnTimeDelete");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), warnOnTimeDelete);
    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonEnd");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), insertEndTask);

    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "hboxEndTask");

    /* Insert combo box using task model. */
    endWidget = gtk_combo_box_new_with_model(InvulgoTrackerApp::app->GetTaskView().GetModel());
    GtkCellRenderer     *renderer = gtk_cell_renderer_text_new ();
    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(endWidget), renderer, TRUE);
    gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(endWidget), renderer, "text", 0);
    GtkTreeIter iter;

    if (InvulgoTrackerApp::app->GetTaskView().FindTask(&iter, endTaskId)) {
        gtk_combo_box_set_active_iter(GTK_COMBO_BOX(endWidget), &iter);
    }
    gtk_widget_show(endWidget);
    gtk_box_pack_end(GTK_BOX(widget), endWidget, TRUE, TRUE, 0);

    /* Continue filling checkboxes. */
    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonSaveSizes");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), saveWindowSizes);
    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonShowSummaryPct");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), showSummaryPercentage);
    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonHideTaskDone");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), hideTaskDone);

    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "hboxSickTask");

    /* Insert combo box using task model. */
    sickWidget = gtk_combo_box_new_with_model(InvulgoTrackerApp::app->GetTaskView().GetModel());
    renderer = gtk_cell_renderer_text_new ();
    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(sickWidget), renderer, TRUE);
    gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(sickWidget), renderer, "text", 0);

    if (InvulgoTrackerApp::app->GetTaskView().FindTask(&iter, sickTaskId)) {
        gtk_combo_box_set_active_iter(GTK_COMBO_BOX(sickWidget), &iter);
    }
    gtk_widget_show(sickWidget);
    gtk_box_pack_end(GTK_BOX(widget), sickWidget, TRUE, TRUE, 0);

    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "hboxHolidayTask");

    /* Insert combo box using task model. */
    holidayWidget = gtk_combo_box_new_with_model(InvulgoTrackerApp::app->GetTaskView().GetModel());
    renderer = gtk_cell_renderer_text_new ();
    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(holidayWidget), renderer, TRUE);
    gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(holidayWidget), renderer, "text", 0);

    if (InvulgoTrackerApp::app->GetTaskView().FindTask(&iter, holidayTaskId)) {
        gtk_combo_box_set_active_iter(GTK_COMBO_BOX(holidayWidget), &iter);
    }
    gtk_widget_show(holidayWidget);
    gtk_box_pack_end(GTK_BOX(widget), holidayWidget, TRUE, TRUE, 0);

    /* Fill color boxes. */
    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "comboboxColorDone");
    GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING);
    for(int qi = 0;colorText[qi];++qi) {
        gtk_list_store_append (store, &iter);
        gtk_list_store_set (store, &iter, 0, colorText[qi], -1);
    }
    gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store));

    renderer = gtk_cell_renderer_text_new ();
    gtk_cell_layout_clear(GTK_CELL_LAYOUT(widget));
    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
    gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widget), doneColor);

    widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "comboboxColorDeadline");
    gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store));
    gtk_cell_layout_clear(GTK_CELL_LAYOUT(widget));
    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
    gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0);
    g_object_unref (store);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widget), deadlineColor);


    /* Set workhours. */
    EntrySet((char*)"entryMondayFrom", workhourMonFrom.TimeText());
    EntrySet((char*)"entryMondayTo", workhourMonTo.TimeText());
    EntrySet((char*)"entryTuesdayFrom", workhourTueFrom.TimeText());
    EntrySet((char*)"entryTuesdayTo", workhourTueTo.TimeText());
    EntrySet((char*)"entryWednesdayFrom", workhourWedFrom.TimeText());
    EntrySet((char*)"entryWednesdayTo", workhourWedTo.TimeText());
    EntrySet((char*)"entryThursdayFrom", workhourThuFrom.TimeText());
    EntrySet((char*)"entryThursdayTo", workhourThuTo.TimeText());
    EntrySet((char*)"entryFridayFrom", workhourFriFrom.TimeText());
    EntrySet((char*)"entryFridayTo", workhourFriTo.TimeText());
    EntrySet((char*)"entrySaturdayFrom", workhourSatFrom.TimeText());
    EntrySet((char*)"entrySaturdayTo", workhourSatTo.TimeText());
    EntrySet((char*)"entrySundayFrom", workhourSunFrom.TimeText());
    EntrySet((char*)"entrySundayTo", workhourSunTo.TimeText());




    /* Show */
    responseHandler = g_signal_connect(window, "response", (GCallback) on_prefs_response, this);
    gtk_widget_show(window);

}

void Prefs::EntrySet(char *label, char *txt)
{
    GtkWidget *widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, label);
    gtk_entry_set_text(GTK_ENTRY(widget), txt);
    free(txt);
}

void Prefs::EntryGet(char *label, TaskTime *tt)
{
    GtkWidget *widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, label);
    const gchar *txt = gtk_entry_get_text(GTK_ENTRY(widget));
    tt->TimeFromString(txt);
}

void Prefs::Response(gint responseId)
{
    GtkTreeIter iter;

    /* Handle result */
    if (responseId == GTK_RESPONSE_OK) {
        GtkWidget *widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonHide");
        hideOnMinimize = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonHideClose");
        hideOnClose = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonWarn");
        warnOnDate = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonWarnTaskDelete");
        warnOnTaskDelete = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonWarnTimeDelete");
        warnOnTimeDelete = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonEnd");
        insertEndTask = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
        if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(endWidget), &iter)) {
            endTaskId = InvulgoTrackerApp::app->GetTaskView().GetTaskId(&iter);
        }
        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonSaveSizes");
        saveWindowSizes = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonShowSummaryPct");
        showSummaryPercentage = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "checkbuttonHideTaskDone");
        hideTaskDone = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));

        if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(sickWidget), &iter)) {
            sickTaskId = InvulgoTrackerApp::app->GetTaskView().GetTaskId(&iter);
        }
        if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(holidayWidget), &iter)) {
            holidayTaskId = InvulgoTrackerApp::app->GetTaskView().GetTaskId(&iter);
        }


        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "comboboxColorDone");
        doneColor = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
        widget = glade_xml_get_widget (InvulgoTrackerApp::gxml, "comboboxColorDeadline");
        deadlineColor = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

        /* Get workhours. */
        EntryGet((char*)"entryMondayFrom",  &workhourMonFrom);
        EntryGet((char*)"entryMondayTo",    &workhourMonTo);
        EntryGet((char*)"entryTuesdayFrom", &workhourTueFrom);
        EntryGet((char*)"entryTuesdayTo",   &workhourTueTo);
        EntryGet((char*)"entryWednesdayFrom", &workhourWedFrom);
        EntryGet((char*)"entryWednesdayTo", &workhourWedTo);
        EntryGet((char*)"entryThursdayFrom", &workhourThuFrom);
        EntryGet((char*)"entryThursdayTo",  &workhourThuTo);
        EntryGet((char*)"entryFridayFrom",  &workhourFriFrom);
        EntryGet((char*)"entryFridayTo",    &workhourFriTo);
        EntryGet((char*)"entrySaturdayFrom", &workhourSatFrom);
        EntryGet((char*)"entrySaturdayTo",  &workhourSatTo);
        EntryGet((char*)"entrySundayFrom",  &workhourSunFrom);
        EntryGet((char*)"entrySundayTo",    &workhourSunTo);

        Save();
    }
    /* Destroy combo box and hide dialog */
    delete this;
}


void Prefs::Load()
{
    xmlDocPtr doc;
    xmlChar *key;
    char *filename = new char[PATH_MAX+1];

    sprintf(filename, "%s%sprefs.xml",g_get_home_dir(),"/.InvulgoTracker/");

    if (!access(filename, F_OK)) {
        doc = xmlParseFile(filename);

        if (doc) {
            xmlNodePtr cur;
            cur = xmlDocGetRootElement(doc);
            if (!xmlStrcmp(cur->name, (const xmlChar *) "Preferences")) {
                cur = cur->xmlChildrenNode;
                while (cur != NULL) {
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"HideOnMinimize"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        hideOnMinimize = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"HideOnClose"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        hideOnClose = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WarnOnDate"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        warnOnDate = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WarnOnTaskDelete"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        warnOnTaskDelete = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WarnOnTimeDelete"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        warnOnTimeDelete = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"InsertEndTask"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        insertEndTask = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"EndTask"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        endTaskId = TaskId((gchar *)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"SickTask"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        sickTaskId = TaskId((gchar *)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"HolidayTask"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        holidayTaskId = TaskId((gchar *)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"SaveWindowSizes"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        saveWindowSizes = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"SavedWindowWidth"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        savedWindowWidth = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"SavedWindowHeight"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        savedWindowHeight = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"SavedVPanePosition"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        savedVPanePosition = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"SavedHPanePosition"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        savedHPanePosition = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"SavedWindowMaximized"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        savedWindowMaximized = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"ShowSummaryPercentage"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        showSummaryPercentage = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"HideTaskDone"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        hideTaskDone = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"DoneColor"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        doneColor = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"DeadlineColor"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        deadlineColor = atol((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourMonFrom"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourMonFrom.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourMonTo"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourMonTo.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourTueFrom"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourTueFrom.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourTueTo"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourTueTo.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourWedFrom"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourWedFrom.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourWedTo"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourWedTo.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourThuFrom"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourThuFrom.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourThuTo"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourThuTo.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourFriFrom"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourFriFrom.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourFriTo"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourFriTo.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourSatFrom"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourSatFrom.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourSatTo"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourSatTo.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourSunFrom"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourSunFrom.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    if ((!xmlStrcmp(cur->name, (const xmlChar *)"WorkhourSunTo"))) {
                        key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
                        workhourSunTo.TimeFromString((char*)key);
                        xmlFree(key);
                    }
                    cur = cur->next;
                }
            }
            xmlFreeDoc(doc);
        }
    }
    delete[] filename;
}


void Prefs::Save()
{
    int rc;
    xmlTextWriterPtr writer;
    xmlDocPtr doc;
    xmlChar *tmp;
    char *txt;

    /* Create a new XmlWriter for DOM, with no compression. */
    writer = xmlNewTextWriterDoc(&doc, 0);
    if (writer == NULL) return;

    rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL);
    if (rc < 0) return;

    rc = xmlTextWriterStartElement(writer, BAD_CAST "Preferences");
    if (rc < 0) return;

    tmp = ConvertInput("Preferences for InvulgoTracker. See www.invulgo.dk for details.", MY_ENCODING);
    rc = xmlTextWriterWriteComment(writer, tmp);
    if (tmp != NULL) xmlFree(tmp);
    if (rc < 0) return;

    /* Save prefs. */
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "HideOnMinimize","%ld", (long)hideOnMinimize);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "HideOnClose","%ld", (long)hideOnClose);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WarnOnDate","%ld", (long)warnOnDate);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WarnOnTaskDelete","%ld", (long)warnOnTaskDelete);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WarnOnTimeDelete","%ld", (long)warnOnTimeDelete);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "InsertEndTask","%ld", (long)insertEndTask);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "EndTask","%s", (const gchar *)endTaskId);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "SickTask","%s", (const gchar *)sickTaskId);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "HolidayTask","%s", (const gchar *)holidayTaskId);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "SaveWindowSizes","%ld", (long)saveWindowSizes);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "SavedWindowWidth","%ld", (long)savedWindowWidth);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "SavedWindowHeight","%ld", (long)savedWindowHeight);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "SavedVPanePosition","%ld", (long)savedVPanePosition);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "SavedHPanePosition","%ld", (long)savedHPanePosition);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "SavedWindowMaximized","%ld", (long)savedWindowMaximized);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "ShowSummaryPercentage","%ld", (long)showSummaryPercentage);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "HideTaskDone","%ld", (long)hideTaskDone);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "DoneColor","%ld", (long)doneColor);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "DeadlineColor","%ld", (long)deadlineColor);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourMonFrom","%s", (const gchar *)(txt = workhourMonFrom.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourMonTo","%s", (const gchar *)(txt = workhourMonTo.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourTueFrom","%s", (const gchar *)(txt = workhourTueFrom.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourTueTo","%s", (const gchar *)(txt = workhourTueTo.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourWedFrom","%s", (const gchar *)(txt = workhourWedFrom.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourWedTo","%s", (const gchar *)(txt = workhourWedTo.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourThuFrom","%s", (const gchar *)(txt = workhourThuFrom.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourThuTo","%s", (const gchar *)(txt = workhourThuTo.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourFriFrom","%s", (const gchar *)(txt = workhourFriFrom.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourFriTo","%s", (const gchar *)(txt = workhourFriTo.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourSatFrom","%s", (const gchar *)(txt = workhourSatFrom.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourSatTo","%s", (const gchar *)(txt = workhourSatTo.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourSunFrom","%s", (const gchar *)(txt = workhourSunFrom.TimeText()));
    free(txt);
    xmlTextWriterWriteFormatElement(writer, BAD_CAST "WorkhourSunTo","%s", (const gchar *)(txt = workhourSunTo.TimeText()));
    free(txt);

    /* Close xml. */
    rc = xmlTextWriterEndElement(writer);
    if (rc < 0) return;

    rc = xmlTextWriterEndDocument(writer);
    if (rc < 0) return;

    xmlFreeTextWriter(writer);

    char *filename = new char[PATH_MAX+1];
    
    sprintf(filename, "%s%sprefs.xml",g_get_home_dir(),"/.InvulgoTracker/");
    
    xmlSaveFormatFile(filename, doc, 1);

    delete[] filename;

    xmlFreeDoc(doc);

    if (subscriber)
        subscriber->Notify(SAVED);

}
